import java.io.*;
import java.util.*;

/**
 * Read is used to read strings from standard input and to error check some
 * input
 */
public abstract class Read
{
    /**
     * Function that reads the first line from standard input. This method
     * is used by many of the other Read methods.
     */
    public static String systemIn()
    {
        String readItem;
        BufferedReader input = new BufferedReader(new InputStreamReader(
                System.in));

        while (true)
        {
            try
            {
                readItem = input.readLine();
                break;
            }
            catch (IOException e)
            {
                e.printStackTrace();
                System.err.println("Couldn't read from standard input");
                System.exit(1);
            }
        }

        return readItem;

    }

    /** 
     * Returns either "y" or "n". Will only return if "y" or "n" is entered.
     * If not, the method will loop until either has been detected.
     */
    public static String yesNo()
    {
        String choice;

        while (true)
        {
            choice = systemIn();

            if (choice.equals("y") == false && choice.equals("n") == false)
            {
                System.err.print("Please enter either \"y\" or \"n\": ");
            }
            else
            {
                break;
            }
        }

        return choice;
    }

    /** 
     * Returns an integer from standard input. Will only return if a valid
     * integer is entered. If not, the method will loop until one has been
     * detected.
     */
    public static int integer()
    {
        int number;
        String input;

        while (true)
        {
            try
            {
                input = systemIn();
                number = Integer.parseInt(input);

                if(number < 1)
                {
                    throw new Exception();
                }

                break;
            }
            catch(NumberFormatException e)
            {
                System.err.print("Please enter a valid integer: ");
            }
            catch(Exception e)
            {
                System.err.print("Please enter an integer above 0: ");
            }
        }

        return number;
    }

    /** 
     * Returns a Date from either standard input or a file. Will only return
     * if a valid Date is entered. If not, the method will loop until one has
     * been detected.
     *
     * @param line if non-empty then check the string entered otherwise use
     * standard input
     */
    public static Date date(String line)
    {
        Date wholeDate;
        String input;
        Calendar currentTime = Calendar.getInstance();

        while (true)
        {
            try
            {
                if (line.equals(""))
                {
                    input = systemIn();
                }
                else
                {
                    input = line;
                }

                String[] dateAndTime = input.split(",");
                if (dateAndTime.length != 2)
                {
                    throw new Exception();
                }
                
                String[] date = dateAndTime[0].split("/");                
                String[] time = dateAndTime[1].split(":");

                if (time.length != 2 || date.length != 3)
                {
                    throw new Exception();
                }

                int day = Integer.parseInt(date[0]);
                int month = Integer.parseInt(date[1]);
                int year = Integer.parseInt(date[2]);
                int hour = Integer.parseInt(time[0]);
                int minute = Integer.parseInt(time[1]);

                if ((day < 1) || (day > 31) || (month < 1) || (month > 12)
                        || (year < 0) || checkTimeFail(hour, minute))
                {
                    throw new Exception();
                }

                wholeDate = setDate(year, month - 1, day, hour, minute);

                if (wholeDate.before(currentTime.getTime()) && line.equals("") == false)
                {
                    throw new Exception();
                }

                break;

            }
            catch (Exception e)
            {
                System.err.print("Please enter a valid date and time: ");
            }
        }

        return wholeDate;
    }

    /** 
     * Returns a Time from either standard input or a file. Will only return
     * if a valid Time is entered. If not, the method will loop until one has
     * been detected.
     *
     * @param line if non-empty then check the string entered otherwise use
     * standard input
     */
    public static Time time(String line)
    {
        Time wholeTime;
        String input;

        while (true)
        {
            try
            {
                if(line.equals(""))
                {
                    input = systemIn();
                }
                else
                {
                    input = line;
                }

                String[] time = input.split(":");
                
                if(time.length != 2)
                {
                    throw new Exception();
                }
                
                int hour = Integer.parseInt(time[0]);
                int minute = Integer.parseInt(time[1]);
                
                if(checkTimeFail(hour, minute))
                {
                    throw new Exception();
                }
                
                wholeTime = new Time(hour, minute);
                
                break;
            }
            catch (Exception e)
            {
                System.err.print("Please enter a valid time: ");
            }
        }

        return wholeTime;
    }

    /** 
     * Create a Date from the coresponding input values. Most values for a
     * Date object are inserted, however seconds are automatically assigned
     * to zero
     */
    public static Date setDate(int year, int month, int date, int hour,
            int minute)
    {
        Calendar cal = Calendar.getInstance();
        cal.set(year, month, date, hour, minute, 0);
        return cal.getTime();
    }

    /** 
     * Checks whether hours and minutes are within the correct ranges
     */
    public static boolean checkTimeFail(int hour, int minute)
    {
        boolean check = false;
        
        if((hour < 0) || (hour > 23) || (minute < 0) || (minute > 59))
        {
           check = true; 
        }
        
        return check;
    }
}
